import re
import shutil
import time
import zipfile
from tkinter import filedialog
from typing import Union
import psutil
import os


def create_zip(workpath, output_filename: str, *args: Union[str, os.PathLike[str]]) -> str | None:  # 将文件进行打包压缩
    """
    :param output_filename: 压缩文件名称路径
    :param args:  被压缩文件路径

    :return: 压缩成功返回压缩文件路径， 压缩失败返回None
    """
    output_filename = os.path.join(workpath, f"{output_filename}.zip")
    try:
        zipf = zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED)
        for directory in args:
            for root, dirs, files in os.walk(directory):
                for file in files:
                    # 使用os.path.relpath来获取相对于directory的文件路径
                    # 但因为我们只想要文件名，所以可以使用os.path.join(root, file).split('/')[-1] 或类似的方法来获取
                    file_in_zip = os.path.join(root, file).replace(directory + os.sep, '')  # 移除目录部分
                    if file_in_zip.startswith(os.sep):  # 如果以路径分隔符开头，则去掉它
                        file_in_zip = file_in_zip[1:]
                    zipf.write(os.path.join(root, file), arcname=file_in_zip)  # 使用arcname参数指定ZIP中的文件名
        zipf.close()
        return output_filename
    except zipfile.BadZipFile:
        return None


def get_usb_path() -> str | None:  # 获取可移动设备路径
    disklist = psutil.disk_partitions(all=True)
    result = None
    for i in disklist:
        try:
            if i.opts.split(',')[1] == 'removable':
                result = i.device
        except IndexError:
            continue
    return result


def copy_to_disk(res, path, need_remove=True) -> bool:  # 将文件移动到指定路径，删除原文件
    path_u = os.path.join(path, time.strftime('%Y%m%d'))
    if not os.path.exists(path_u):
        os.makedirs(path_u)
    shutil.copy(res, path_u)
    if need_remove:
        os.remove(res)
    return True


def open_dir():
    file_path = filedialog.askopenfilename(
        title="选择压缩包",
        filetypes=[
            ("ZIP文件", "*.zip"),
        ]
    )
    return file_path


def unzip_file(zip_path, extract_to):  # 解压压缩包到指定路径
    with zipfile.ZipFile(zip_path, 'r') as zip_ref:
        zip_ref.extractall(extract_to)


def find_files(path, end='.txt'):  # 获取指定文件夹下是否存在指定后缀文件  ->  文件路径列表, 文件名称列表
    name_list = []
    path_list = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith(end):
                path_list.append(os.path.join(root, file))
                name_list.append(file.replace(end, ''))
    return path_list, name_list


def makedir(workpath: str, path: str, is_work: bool = True) -> str:
    if is_work:
        if workpath not in path:
            path = os.path.join(workpath, path)
    if not os.path.exists(path):
        os.makedirs(path, exist_ok=True)
    return path


def input_time(date_var):  # 日期格式检查
    riqi_s = date_var.get()
    listrq = re.findall(r"\D", riqi_s)
    for i in listrq:
        riqi_s = riqi_s.replace(i, '')
    if len(riqi_s) == 8:
        year1 = riqi_s[0:4]
        mon1 = riqi_s[4:6]
        day1 = riqi_s[6:]
        year = int(year1)
        mon = int(mon1)
        day = int(day1)
        if 2099 >= year >= 1970 and 0 < mon < 13 and 0 < day < 32:
            if mon == 2 and year % 4 != 0 and day < 29:
                date_var.set(year1 + mon1 + day1)
                return True
            elif (mon == 2 and year % 400 == 0 and day < 30) or (
                    mon == 2 and year % 100 != 0 and day < 30 and year % 4 == 0):
                date_var.set(year1 + mon1 + day1)
                return True
            elif mon in [1, 3, 5, 7, 8, 10, 12] and day < 32:
                date_var.set(year1 + mon1 + day1)
                return True
            elif mon in [4, 6, 9, 11] and day < 31:
                date_var.set(year1 + mon1 + day1)
                return True
            else:
                date_var.set('')
                # message = '日期输入错误,请检查日期'
                return False
        else:
            date_var.set('')
            # message = '日期输入错误,请检查日期'
            return False
    else:
        date_var.set('')
        # message = '请输入正确的格式，日期和月份请用0补齐为双位数'
        return False
